// app_ble.c
#include "app_ble.h"
#include "at_task.h"
#include "bluenrg1_api.h"

static uint16_t adv_len = 0;
static uint8_t adv_data[31] = {
    0x02,AD_TYPE_FLAGS, FLAG_BIT_LE_GENERAL_DISCOVERABLE_MODE|FLAG_BIT_BR_EDR_NOT_SUPPORTED,
	0x08,0x09,'B','l','u','e','N','R','G',
	0x12,0xFF,
};

uint8_t name[] = {'B','l','u','e','N','R','G',};

uint8_t dev_name[MAX_DEV_LEN+1] = {DEF_DEV_NAME};

static uint8_t  advertising = 0;
// 作为从机时的连接句柄
static uint16_t con_handle_S = 0;

static at_obj_t *at_obj;


static master_device masters[1];




extern uint16_t TXCharHandle, RXCharHandle;


void app_ble_init(at_obj_t* obj)
{
  at_obj = obj;
}

// 生成静态MAC地址参考函数
void generate_static_mac_addr(uint8_t bdaddr[6])
{
	// get UID
	BYTE text1[8];
	uint32_t *paddr0 = (uint32_t*)0x100007F4;
	uint32_t *paddr1 = (uint32_t*)0x100007F8;
	uint32_t word0 = *paddr0;
	uint32_t word1 = *paddr1;
	memcpy(text1,&word0,sizeof(word0));
	memcpy(&text1[4],&word1,sizeof(word1));
	BYTE buf[SHA256_BLOCK_SIZE];
	SHA256_CTX ctx;
	sha256_init(&ctx);
	sha256_update(&ctx, text1, sizeof(text1));
	sha256_final(&ctx, buf);
	buf[5] |= 0xC0;
	memcpy(bdaddr,buf,6);
}


void enable_adv(uint8_t Enable)
{
	
	if(Enable){
		uint8_t ret = aci_gap_set_discoverable(ADV_IND, 100, 100, PUBLIC_ADDR, NO_WHITE_LIST_USE,
																	 sizeof(name), name, 0, NULL, 0, 0);
		if (ret != BLE_STATUS_SUCCESS)
			COMPrintf ("Error in aci_gap_set_advertising_enable(): 0x%02x\r\n", ret);
		else{
			COMPrintf ("aci_gap_set_advertising_enable() --> SUCCESS\r\n");
			advertising = true;
		}
	}else{
	
	
	}
}



void default_ble_init(void)
{
	uint8_t mac[6];
	uint16_t service_handle;
	uint16_t dev_name_char_handle;
	uint16_t appearance_char_handle;
	generate_static_mac_addr(mac);
	tBleStatus ret = aci_hal_write_config_data(CONFIG_DATA_STATIC_RANDOM_ADDRESS, 6, mac);
	if(ret != BLE_STATUS_SUCCESS){
        COMPrintf("aci_hal_write_config_data:%x \r\n", ret);
	}

    ret = aci_hal_set_tx_power_level(1, 4);
	if(ret != BLE_STATUS_SUCCESS){
		COMPrintf("aci_hal_set_tx_power_level:%x \r\n", ret);
	}
	  /* GATT Init */
  ret = aci_gatt_init();
  if (ret != BLE_STATUS_SUCCESS) {
    printf ("Error in aci_gatt_init(): 0x%02x\r\n", ret);
    return;
  } else {
    printf ("aci_gatt_init() --> SUCCESS\r\n");
  }
  
  /* GAP Init */
  ret = aci_gap_init(0xff, 0x00, 0x08, &service_handle, 
                     &dev_name_char_handle, &appearance_char_handle);
  if (ret != BLE_STATUS_SUCCESS) {
    printf ("Error in aci_gap_init() 0x%02x\r\n", ret);
    return;
  } else {
    printf ("aci_gap_init() --> SUCCESS\r\n");
  }

  /* Set the device name */
  ret = aci_gatt_update_char_value_ext(0,service_handle, dev_name_char_handle,0,sizeof(name),0, sizeof(name), name);
  if (ret != BLE_STATUS_SUCCESS) {
    printf ("Error in Gatt Update characteristic value 0x%02x\r\n", ret);
    return;
  } else {
    printf ("aci_gatt_update_char_value_ext() --> SUCCESS\r\n");
  }


	ret = Add_SerialPort_Service();
	if(ret != BLE_STATUS_SUCCESS){
		printf("Add_SerialPort_Service:%x \r\n", ret);
	}





	enable_adv(true);
  
  //aci_gap_update_adv_data(MANUF_DATA_SIZE, manuf_data);
  //COMPrintf("Set advertising data %02X\n", ret); 

  

}





int notify_data_handler(at_urc_info_t *info)
{
    uint16_t pos = CMD_LEN(NOTIFY_DATA)+1;
	uint16_t len = info->urclen - pos -1;

	if(masters[0].conn_handle == 0){
		at_exec_cmd(at_obj, NULL,"AT+%s=Didn't create connectione yet!",enumToStr(NOTIFY_DATA));
        return 0;
	}

	if(len > 0){
      tBleStatus ret  =  aci_gatt_update_char_value_ext(masters[0].conn_handle,SerialPortServHandle, TXCharHandle,1, len,0,len, (uint8_t*)(info->urcbuf+pos));
      if(ret == BLE_STATUS_SUCCESS){
        printf("Data sent to master:%d \n", len);
		at_exec_cmd(at_obj, NULL,"AT+%s=OK",enumToStr(NOTIFY_DATA));
      }
      else
        COMPrintf(" failed  to sent \n");
	}
    return 0;
}


void hci_le_enhanced_connection_complete_event(uint8_t Status,
                                               uint16_t Connection_Handle,
                                               uint8_t Role,
                                               uint8_t Peer_Address_Type,
                                               uint8_t Peer_Address[6],
                                               uint8_t Local_Resolvable_Private_Address[6],
                                               uint8_t Peer_Resolvable_Private_Address[6],
                                               uint16_t Conn_Interval,
                                               uint16_t Conn_Latency,
                                               uint16_t Supervision_Timeout,
                                               uint8_t Master_Clock_Accuracy)
{

  if(Status == 0){
  	  masters[0].conn_handle = Connection_Handle;
	    masters[0].address_type = Peer_Address_Type;
      memcpy(masters[0].address, Peer_Address, 6);
	    aci_gatt_exchange_config(Connection_Handle);
      at_exec_cmd(at_obj, NULL, "AT+%s=Con_Handle:%x,Role:%s,MAC:%02X:%02X:%02X:%02X:%02X:%02X",
	  											enumToStr(ONCONNECTED), 
	  											Connection_Handle,
	  											(Role==1?"Master":"Slave"),
	  											Peer_Address[5],Peer_Address[4],Peer_Address[3],
	  											Peer_Address[2],Peer_Address[1],Peer_Address[0]
	  											);
												
  }

}


void hci_disconnection_complete_event(uint8_t Status,
                                      uint16_t Connection_Handle,
                                      uint8_t Reason)
{
	at_exec_cmd(at_obj, NULL, "AT+%s=Con_Handle:%x,Reason:%x",
														enumToStr(ONDISCONNECTED), 
														Connection_Handle,
														Reason
														);
	//enable_adv(ENABLE);
}


/**
 * @brief This event is generated to the application by the GATT server when a
 *        client modifies any attribute on the server, as consequence of one of
 *        the following GATT procedures: - write without response - signed write
 *        without response - write characteristic value - write long
 *        characteristic value - reliable write.
 * @param Connection_Handle The connection handle which modified the attribute.
 * @param Attr_Handle Handle of the attribute that was modified.
 * @param Offset SoC mode: the offset is never used and it is always 0. Network
 *        coprocessor mode:     - Bits 0-14: offset of the reported value inside
 *        the attribute.     - Bit 15: if the entire value of the attribute does
 *        not fit inside a single ACI_GATT_ATTRIBUTE_MODIFIED_EVENT event, this
 *        bit is set to 1 to notify that other ACI_GATT_ATTRIBUTE_MODIFIED_EVENT
 *        events will follow to report the remaining value.
 * @param Attr_Data_Length Length of Attr_Data in octets
 * @param Attr_Data The modified value
 * @retval None
 */
void aci_gatt_attribute_modified_event(uint16_t Connection_Handle,
                                       uint16_t Attr_Handle,
                                       uint16_t Offset,
                                       uint16_t Attr_Data_Length,
                                       uint8_t Attr_Data[])
{
  uint8_t buffer_out[532] = {'\0'};

  printf("aci_gatt_srv_attribute_modified_event\r\n");
  for(int i=0;i<Attr_Data_Length;i++)
  {
    sprintf((char*)buffer_out+2*i,"%02X", Attr_Data[i]);
  }
	
  at_task_exec_cmd("AT+%s=%s",enumToStr(ATT_MODEFIED),buffer_out);

}




void aci_gatt_srv_write_event(uint16_t Connection_Handle,
                              uint8_t Resp_Needed,
                              uint16_t Attribute_Handle,
                              uint16_t Data_Length,
                              uint8_t Data[])
{
  printf("aci_gatt_srv_write_event\n");
  uint8_t buffer_out[512]={'\0'};
	//ATT_MODEFIED
	for(int i=0;i<Data_Length;i++)
	{
	    sprintf((char*)buffer_out+2*i,"%02X", Data[i]);
	}
	at_task_exec_cmd("AT+%s=%s",enumToStr(GATT_WRITE),buffer_out);

}


/**
 * @brief The LE Advertising Report event indicates that a Bluetooth device or
 *        multiple Bluetooth devices have responded to an active scan or
 *        received some information during a passive scan. The Controller may
 *        queue these advertising reports and send information from multiple
 *        devices in one LE Advertising Report event.
 * @param Num_Reports Number of responses in this event.
 *        Values:
 *        - 0x01
 * @param Advertising_Report See @ref Advertising_Report_t
 * @retval None
 */
//void hci_le_advertising_report_event(uint8_t Num_Reports,
//                                     Advertising_Report_t Advertising_Report[])
//{

//   //at_task_exec_cmd();
//}


